#pragma once

#include "cybertron/DefinesCore.hpp"
#include <asio.hpp>
#include <thread>
#include <vector>
#include <string>
#include <mutex>

CYBERTRON_BEGIN

class SocketTcpClientThreads
{
public:
	SocketTcpClientThreads(const std::string& name);
	~SocketTcpClientThreads();

	void setupContext();
	void start(int numThreads = -1);
	void stop();

public:
	std::shared_ptr<asio::io_context> getContext() const
	{
		return mpIoContext;
	}

	void addSocket(SocketBasePtr pSocket);
	void removeSocket(SocketBase* pSocket);

	void setHeartbeatSeconds(unsigned int seconds)
	{
		mHeartbeatSeconds = seconds;
	}

	unsigned int getHeartbeatSeconds() const
	{
		return mHeartbeatSeconds;
	}

private:
	void onHeartbeat();

private:
	SocketTcpClientThreads(const SocketTcpClientThreads&);
	SocketTcpClientThreads(SocketTcpClientThreads&&);
	SocketTcpClientThreads& operator = (const SocketTcpClientThreads&);
	SocketTcpClientThreads& operator = (SocketTcpClientThreads&&);

private:
	std::shared_ptr<asio::io_context> mpIoContext;
	std::vector<std::shared_ptr<std::thread>> mThreads;
	std::string mName;
	std::atomic<unsigned int> mHeartbeatSeconds;

	bool mThreadRunning;
	std::shared_ptr<std::thread> mHeartbeatThread;
	std::recursive_mutex mHeartbeatMutex;
	std::vector<std::weak_ptr<SocketBase>> mClientSockets;
};

CYBERTRON_END
